package org.study.mybatisplus.dynamic.boot.util;

import lombok.*;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 作用描述
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2025年10月21日
 */
@Slf4j
@UtilityClass
public class TDengineUtils {
    /**
     * TDengine数据类型枚举类
     */
    @Getter
    @AllArgsConstructor
    public enum DateTypeEnum {
        TIMESTAMP(1, "TIMESTAMP", "时间戳", "占8字节。缺省精度毫秒，可支持微秒和纳秒"),
        INT(2, "INT", "整型", "占4字节。范围：[-2^31, 2^31-1]"),
        INT_UNSIGNED(3, "INT UNSIGNED", "无符号整型", "占4字节。范围：[0, 2^32-1]"),
        BIGINT(4, "BIGINT", "长整型", "占8字节。范围：[-2^63, 2^63-1]"),
        BIGINT_UNSIGNED(5, "BIGINT UNSIGNED", "无符号长整型", "占8字节。范围：[0, 2^64-1]"),
        FLOAT(6, "FLOAT", "单精度浮点型", "占4字节。有效位数6-7，范围：[-3.4E38, 3.4E38]"),
        DOUBLE(7, "DOUBLE", "双精度浮点型", "占8字节。有效位数15-16，范围：[-1.7E308, 1.7E308]"),
        BINARY(8, "BINARY", "单字节字符串", "自定义长度。记录单字节字符串，建议只用于处理ASCII可见字符，中文等多字节字符需使用NCHAR"),
        SMALLINT(9, "SMALLINT", "短整型", "占2字节。范围：[-32768, 32767]"),
        SMALLINT_UNSIGNED(10, "SMALLINT UNSIGNED", "无符号短整型", "占2字节。范围：[0, 65535]"),
        TINYINT(11, "TINYINT", "单字节整型", "占1字节。范围：[-128, 127]"),
        TINYINT_UNSIGNED(12, "TINYINT UNSIGNED", "无符号单字节整型", "占1字节。范围：[0, 255]"),
        BOOL(13, "BOOL", "布尔型", "占1字节。范围：[TRUE，FALSE]"),
        NCHAR(14, "NCHAR", "多字节字符串", "自定义长度。记录包含多字节字符在内的字符串，如中文字符。每个NCHAR字符占用4字节的存储空间。字符串两端使用单引号引用，字符串内的单引号需用转义字符\\'。NCHAR使用时须指定字符串大小，类型为NCHAR(10)的列表示此列的字符串最多存储10个NCHAR字符。如果用户字符串长度超出声明长度，将会报错。"),
        JSON(15, "JSON", "JSON数据类型", "只有Tag可以是JSON格式"),
        VARCHAR(16, "VARCHAR", "单字节字符串", "自定义长度。BINARY类型的别名"),
        GEOMETRY(17, "GEOMETRY", "几何类型", "自定义长度。v3.1.0.0开始支持"),
        VARBINARY(18, "VARBINARY", "可变长二进制类型", "自定义长度。可变长的二进制数据，v3.1.1.0开始支持"),
        DECIMAL(19, "DECIMAL", "高精度数值型", "占8或16字节。取值范围取决于类型中指定的precision和scale，自v3.3.6.0开始支持"),
        BLOB(20, "BLOB", "可变长的二进制数据", "最大长度 4MB"),
        ;

        private Integer code;
        private String dateType;
        private String name;
        private String desc;

        public static String getDateType(Integer code) {
            if (code != null) {
                for (DateTypeEnum dateTypeEnum : DateTypeEnum.values()) {
                    if (dateTypeEnum.code.equals(code)) {
                        return dateTypeEnum.dateType;
                    }
                }
            }
            throw new RuntimeException("不支持该数据类型");
        }

        public static String getDateType(String name) {
            if (StringUtils.isNotBlank(name)) {
                for (DateTypeEnum dateTypeEnum : DateTypeEnum.values()) {
                    if (dateTypeEnum.name.equals(name)) {
                        return dateTypeEnum.dateType;
                    }
                }
            }
            throw new RuntimeException("不支持该数据类型");
        }
    }

    @Data
    public class DateType {
        private Integer code;
        private String dateType;
        private String name;
        private String desc;
    }

    /**
     * 将TDengine支持数据类型枚举转为普通对象类
     */
    public List<DateType> getDateType() {
        List<DateType> result = Lists.newArrayList();
        for (DateTypeEnum dateTypeEnum : DateTypeEnum.values()) {
            DateType dateType = new DateType();
            dateType.setCode(dateTypeEnum.getCode());
            dateType.setDateType(dateTypeEnum.getDateType());
            dateType.setName(dateTypeEnum.getName());
            dateType.setDesc(dateTypeEnum.getDesc());
            result.add(dateType);
        }
        return result;
    }

    /**
     * 获取TDengine支持的所有数据类型
     */
    public List<String> getAllDateType() {
        List<String> result = Lists.newArrayList();
        for (DateTypeEnum dateTypeEnum : DateTypeEnum.values()) {
            result.add(dateTypeEnum.getDateType());
        }
        return result;
    }

    /**
     * 获取TDengine支持的所有数值数据类型
     */
    public List<String> getNumberDateType() {
        List<String> result = new ArrayList<>() {{
            this.add(DateTypeEnum.INT.getDateType());
            this.add(DateTypeEnum.INT_UNSIGNED.getDateType());
            this.add(DateTypeEnum.BIGINT.getDateType());
            this.add(DateTypeEnum.BIGINT_UNSIGNED.getDateType());
            this.add(DateTypeEnum.FLOAT.getDateType());
            this.add(DateTypeEnum.DOUBLE.getDateType());
            this.add(DateTypeEnum.SMALLINT.getDateType());
            this.add(DateTypeEnum.SMALLINT_UNSIGNED.getDateType());
            this.add(DateTypeEnum.TINYINT.getDateType());
            this.add(DateTypeEnum.TINYINT_UNSIGNED.getDateType());
            this.add(DateTypeEnum.DECIMAL.getDateType());
        }};
        return result;
    }
}
